package cn.zwk.product.service.impl;

import cn.zwk.common.constant.ProductConstant;
import cn.zwk.common.exception.NoStockException;
import cn.zwk.common.to.SkuHasStockTo;
import cn.zwk.common.to.SkuReductionTo;
import cn.zwk.common.to.SpuBoundTo;
import cn.zwk.common.to.es.SkuEsModel;
import cn.zwk.common.utils.R;
import cn.zwk.product.dao.SpuInfoDao;
import cn.zwk.product.entity.*;
import cn.zwk.product.feign.CouponFeignService;
import cn.zwk.product.feign.SearchClient;
import cn.zwk.product.feign.WareFeignService;
import cn.zwk.product.service.*;
import cn.zwk.product.vo.*;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public abstract class SpuInfoAbstractService extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private SpuInfoDescService spuDescService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private AttrService attrService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private SpuInfoService spuInfoService;
    @Autowired
    private ProductAttrValueService productAttrService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;


    @Autowired
    private CouponFeignService couponClient;
    @Autowired
    private WareFeignService wareClient;
    @Autowired
    private SearchClient searchClient;

    /**
     * 保存spu相关信息
     * @param vo
     */
    @Override
    @Transactional
    public void saveSpuInfo(SpuSaveVo vo) {
        //1.保存spu基本信息
        SpuInfoEntity spuInfo = this.save(vo);

        //2.保存图片信息
        saveDecriptInfo(spuInfo.getId(), vo.getDecript());

        //3.保存图片集
        saveImages(spuInfo.getId(), vo.getImages());

        //4.保存spu规格参数信息
        saveAttrValue(spuInfo.getId(), vo.getBaseAttrs());

        //5.保存积分信息
        saveMemberInfo(spuInfo.getId(), vo.getBounds());

        //6.保存sku信息
        saveAboutSkus(spuInfo, vo.getSkus());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void up(Long spuId) throws NoStockException {
        //1.查询当前spu所有可供检索的属性
        List<ProductAttrValueEntity> searchAttr = getSpuSearchAttr(spuId);

        //2.查询当前spu的所有sku信息
        List<SkuInfoEntity> skus = skuInfoService.lambdaQuery().eq(SkuInfoEntity::getSpuId, spuId).list();

        //3.获取每个商品是否有库存
        Map<Long, Boolean> skuHasStockMap = getSkusHasStock(skus);

        //4.将保存到es中
        saveEsModel(searchAttr, skuHasStockMap, skus);

        //5.修改spu的状态
        this.lambdaUpdate().eq(SpuInfoEntity::getId, spuId).set(SpuInfoEntity::getPublishStatus, ProductConstant.ProductStatusEnum.SPU_UP.getCode()).update();
    }

    private void saveEsModel(List<ProductAttrValueEntity> searchAttr, Map<Long, Boolean> stockMap, List<SkuInfoEntity> skus) {
        List<SkuEsModel.Attrs> attrModels = searchAttr.stream().map(
                attr -> new SkuEsModel.Attrs(attr.getAttrId(), attr.getAttrName(), attr.getAttrValue())
        ).collect(Collectors.toList());

        Long brandId = skus.get(0).getBrandId();
        Long catalogId = skus.get(0).getCatalogId();
        BrandEntity brandEntity = brandService.getById(brandId);
        CategoryEntity categoryEntity = categoryService.getById(catalogId);

        List<SkuEsModel> skuModels = skus.stream().map(sku -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(sku, skuEsModel);
            skuEsModel.setSkuPrice(sku.getPrice());
            skuEsModel.setSkuImg(sku.getSkuDefaultImg());
            skuEsModel.setSkuTitle(sku.getSkuTitle());

            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());
            skuEsModel.setCatalogName(categoryEntity.getName());

            skuEsModel.setAttrs(attrModels);
            skuEsModel.setHasStock(stockMap.get(sku.getSkuId()));

            return skuEsModel;
        }).collect(Collectors.toList());
        searchClient.productStatusUp(skuModels);
    }

    private Map<Long, Boolean> getSkusHasStock(List<SkuInfoEntity> skus) {
        Map<Long, Boolean> result = new HashMap<>();
        List<Long> skuIds = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        List<SkuHasStockTo> hasStocks = null;
        try {
            R r = wareClient.getSkuHasStock(skuIds);
            hasStocks = (List<SkuHasStockTo>) r.getData(new TypeReference<List<SkuHasStockTo>>() {
            });
        } catch (Exception e) {
            log.error("库存服务查询异常：原因{}", e);
        }
        if (hasStocks == null) {
            throw new NoStockException("该商品没有库存，无法上架");
        }
        boolean hasStock = false;
        for (SkuHasStockTo stock : hasStocks) {
            boolean curStock = stock.getHasStock();
            result.put(stock.getSkuId(), curStock);
            if (curStock) hasStock = true;
        }
        if (!hasStock) {
            throw new NoStockException("该商品没有库存，无法上架");
        }
        return result;
    }

    //查询当前spu所有可供检索的属性
    private List<ProductAttrValueEntity> getSpuSearchAttr(Long spuId) {
        //1.查询spu所有属性
        List<ProductAttrValueEntity> attrs = productAttrService.lambdaQuery().eq(ProductAttrValueEntity::getSpuId, spuId).list();
        //2.过滤出快速展示的属性
        List<Long> attrIds = attrs.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
        //3.查询这些属性是否是检索属性
        Set<Long> searchAttrIds = productAttrService.selectSearchAttrs(attrIds);
        attrs = attrs.stream().filter(attr -> searchAttrIds.contains(attr.getAttrId())).collect(Collectors.toList());
        return attrs;
    }


    /**
     * 保存sku相关信息
     * @param spu
     * @param skus
     */
    private void saveAboutSkus(SpuInfoEntity spu, List<Skus> skus) {
        Long spuId = spu.getId();
        Long cid = spu.getCatalogId();
        Long brandId = spu.getBrandId();
        for (Skus sku : skus) {
            //1 保存sku基本信息
            SkuInfoEntity skuInfo = saveSkuInfo(spuId, cid, brandId, sku);
            //2 保存sku的图片信息
            saveSkuImages(skuInfo.getSkuId(), sku.getImages());
            //3 保存sku的销售属性信息
            saveSkuSaleAttrValue(skuInfo.getSkuId(), sku.getAttr());
            //4 保存sku的优惠、满减等信息
            saveSkuBounds(skuInfo.getSkuId(), sku);
        }
    }

    /**
     * 6.4保存sku的优惠、满减等信息
     */
    private void saveSkuBounds(Long skuId, Skus sku) {
        if (sku.getFullCount() <= 0 && sku.getFullPrice().compareTo(BigDecimal.ZERO) <= 0) return;

        SkuReductionTo reductionTo = new SkuReductionTo();
        BeanUtils.copyProperties(sku, reductionTo);
        reductionTo.setSkuId(skuId);
        R res = couponClient.saveSkuReduction(reductionTo);
        if (res.getCode() != 0) {
            log.error("远程保存sku优惠信息失败");
            throw new RuntimeException("远程保存sku优惠信息失败");
        }
    }

    /**
     * 6.3保存sku销售属性信息
     */
    private void saveSkuSaleAttrValue(Long skuId, List<Attr> attrs) {
        List<SkuSaleAttrValueEntity> collect = attrs.stream().map(a -> {
            SkuSaleAttrValueEntity attrValue = new SkuSaleAttrValueEntity();
            BeanUtils.copyProperties(a, attrValue);
            attrValue.setSkuId(skuId);
            return attrValue;
        }).collect(Collectors.toList());
        skuSaleAttrValueService.saveBatch(collect);
    }

    /**
     * 6.2保存sku图片信息
     */
    private void saveSkuImages(Long skuId, List<Images> images) {
        List<SkuImagesEntity> skuImages = images.stream().map(img ->
                        SkuImagesEntity.builder()
                                .skuId(skuId)
                                .imgUrl(img.getImgUrl())
                                .defaultImg(img.getDefaultImg())
                                .build())
                .filter(img -> !StringUtils.isEmpty(img.getImgUrl()))
                .collect(Collectors.toList());
        skuImagesService.saveBatch(skuImages);
    }

    /**
     * 6.1保存sku基本信息
     */
    private SkuInfoEntity saveSkuInfo(Long spuId, Long cid, Long brandId, Skus sku) {
        SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
        BeanUtils.copyProperties(sku, skuInfoEntity);
        for (Images image : sku.getImages()) {
            if (image.getDefaultImg() == 1) {
                skuInfoEntity.setSkuDefaultImg(image.getImgUrl());
                break;
            }
        }
        skuInfoEntity.setSpuId(spuId);
        skuInfoEntity.setCatalogId(cid);
        skuInfoEntity.setBrandId(brandId);
        skuInfoService.save(skuInfoEntity);
        return skuInfoEntity;
    }

    /**
     * 5.保存积分信息
     */
    private void saveMemberInfo(Long spuId, Bounds bounds) {
        SpuBoundTo dto = new SpuBoundTo();
        dto.setSpuId(spuId);
        dto.setBuyBounds(bounds.getBuyBounds());
        dto.setGrowBounds(bounds.getGrowBounds());
        R r = couponClient.saveSpuBounds(dto);
        if (r.getCode() != 0) {
            log.error("远程保存spu积分信息失败");
            throw new RuntimeException("远程保存spu积分信息失败");
        }
    }

    /**
     * 4.保存spu规格参数信息
     */
    private void saveAttrValue(Long spuId, List<BaseAttrs> baseAttrs) {
        List<ProductAttrValueEntity> collect = baseAttrs.stream().map(attr -> {
                    AttrEntity AttrEntity = attrService.getById(attr.getAttrId());
                    ProductAttrValueEntity attrValue = ProductAttrValueEntity.builder()
                            .spuId(spuId)
                            .attrId(attr.getAttrId())
                            .attrName(AttrEntity.getAttrName())
                            .attrValue(attr.getAttrValues())
                            .quickShow(attr.getShowDesc())
                            .build();
                    return attrValue;
                }
        ).collect(Collectors.toList());
        productAttrValueService.saveBatch(collect);
    }

    /**
     * 3.保存spu图片集
     */
    private void saveImages(Long spuId, List<String> images) {
        List<SpuImagesEntity> collect = images.stream().map(url ->
                SpuImagesEntity.builder()
                        .spuId(spuId)
                        .imgUrl(url)
                        .build()
        ).collect(Collectors.toList());
        spuImagesService.saveBatch(collect);
    }

    /**
     * 2.保存spu描述信息
     */
    private void saveDecriptInfo(Long spuId, List<String> decript) {
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuId);
        String decripts = StringUtils.collectionToDelimitedString(decript, ",");
        descEntity.setDecript(decripts);
        spuDescService.save(descEntity);
    }

    /**
     * 1.保存spu基本信息
     */
    private SpuInfoEntity save(SpuSaveVo vo) {
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(vo, spuInfoEntity);
        spuInfoEntity.setPublishStatus(0);
        spuInfoService.save(spuInfoEntity);
        return spuInfoEntity;
    }
}
